package com.sumainfor.common.util;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.asn1.dvcs.Data;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Period;
import java.util.*;

/**
 * 日期处理
 */
public class DateUtils {
    /**
     * 时间格式(yyyy-MM-dd)
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date 日期
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式为：yyyy-MM-dd
     *
     * @param date    日期
     * @param pattern 格式，如：DateUtils.DATE_TIME_PATTERN
     * @return 返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根据周数，获取开始日期、结束日期
     *
     * @param week 周期  0本周，-1上周，-2上上周，1下周，2下下周
     * @return 返回date[0]开始日期、date[1]结束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 对日期的【秒】进行加/减
     *
     * @param date    日期
     * @param seconds 秒数，负数为减
     * @return 加/减几秒后的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 对日期的【分钟】进行加/减
     *
     * @param date    日期
     * @param minutes 分钟数，负数为减
     * @return 加/减几分钟后的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【周】进行加/减
     *
     * @param date  日期
     * @param weeks 周数，负数为减
     * @return 加/减几周后的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonthsToEnd(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return addDateDays(dateTime.plusMonths(months).toDate(), -1);
    }

    /**
     * 对日期的【年】进行加/减
     *
     * @param date  日期
     * @param years 年数，负数为减
     * @return 加/减几年后的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }

    /**
     * 循环遍历Map集合 格式化时间
     *
     * @param map
     */
    public static void formatDateByMap(Map<String, Object> map, String pattern) {
        if (MapUtils.isNotEmpty(map)) {
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                if (entry.getValue() instanceof Date) {
                    map.put(entry.getKey(), format((Date) entry.getValue(), pattern));
                } else if (entry.getValue() instanceof Timestamp) {
                    Timestamp timestamp = (Timestamp) entry.getValue();
                    map.put(entry.getKey(), format(timestamp, pattern));
                }
            }
        }
    }

    public static void formatDateByMap(Map<String, Object> map) {
        formatDateByMap(map, "yyyy-MM-dd");
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param nowTime   当前时间
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     * @author jqlin
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param list 对应格式化的字符串集合(指定格式字符串yyyy-MM-dd HH:mm:ss)
     * @return
     * @throws ParseException
     */
    public static List<String> sortListDesc(List<String> list) throws ParseException {
        List<String> retStr = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<Long, String> map = new TreeMap<Long, String>();
        for (int i = 0; i < list.size(); i++) {
            String dateStr = list.get(i);
            map.put(sdf.parse(dateStr).getTime(), dateStr);
        }
        Collection<String> coll = map.values();
        retStr.addAll(coll);
        Collections.reverse(retStr);
        return retStr;
    }

    /**
     * 获取时间的所在月份的第一天
     *
     * @param dateString
     * @return
     */
    public static String getMonthFirstDay(String dateString) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String first = sdf.format(calendar.getTime());
        return first;
    }

    /**
     * 获取日期的所在的月份的最后一天
     *
     * @param dateString
     * @return
     */
    public static String getMonthLastDay(String dateString) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        String last = sdf.format(calendar.getTime());
        return last;
    }

    /**
     * 获取两个日期之间相差的天数
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Integer betweenDay(String beginDate, String endDate) {
        java.time.LocalDate beginDateTime = java.time.LocalDate.parse(beginDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        java.time.LocalDate endDateTime = java.time.LocalDate.parse(endDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return Period.between(beginDateTime, endDateTime).getDays();
    }

    /**
     * 获取两个日期之间相差的月数
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Integer betweenMonth(String beginDate, String endDate) {
        java.time.LocalDate beginDateTime = java.time.LocalDate.parse(beginDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        java.time.LocalDate endDateTime = java.time.LocalDate.parse(endDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return Period.between(beginDateTime, endDateTime).getMonths();
    }

    /**
     * 获取日期所在月的天数
     *
     * @param date
     * @return
     */
    public static Integer getMonthOfDay(String date) {
        java.time.LocalDate dateTime = java.time.LocalDate.parse(date, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        return dateTime.lengthOfMonth();
    }

    /**
     * 比较两个日期是否在同一个月里
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Boolean checkMonth(String beginDate, String endDate) {
//        System.out.println("beginDate:"+beginDate);
//        System.out.println("endDate:"+endDate);
        //字符串转换成 LocalDate
        java.time.LocalDate beginDateTime = java.time.LocalDate.parse(beginDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        java.time.LocalDate endDateTime = java.time.LocalDate.parse(endDate, java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
//        System.out.println("beginDateTime:"+beginDateTime+"===endDateTime:"+endDateTime);
        //获取两个日期的年
        Integer beginYear = beginDateTime.getYear();
        Integer endYear = endDateTime.getYear();
//        System.out.println("beginYear:"+beginYear+"===endYear:"+endYear);
        //获取两个日期的月
        Integer beginMonth = beginDateTime.getMonthValue();
        Integer endMonth = endDateTime.getMonthValue();
//        System.out.println("beginMonth:"+beginMonth+"===endMonth:"+endMonth);
        if (String.valueOf(beginYear).equals(String.valueOf(endYear))
                &&
                String.valueOf(beginMonth).equals(String.valueOf(endMonth))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 比较两个日期的大小（yyyy-MM-dd）2 date1在date2之前 2 date1在date2之后 0 相等 3异常
     *
     * @param date1
     * @param date2
     * @param format
     * @return
     */
    public static String compare_date(String date1, String date2, String format) {
        DateFormat df = new SimpleDateFormat(format);
        try {
            Date dt1 = df.parse(date1);
            Date dt2 = df.parse(date2);
            if (dt1.getTime() > dt2.getTime()) {
                System.out.println("dt1 在dt2后");
                return "1";
            } else if (dt1.getTime() < dt2.getTime()) {
                System.out.println("dt1在dt2前");
                return "2";
            } else if (dt1.getTime() == dt2.getTime()) {
                return "0";
            } else {
                return "3";
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return "3";
    }

    /**
     * 获取当前时间的字符串
     *
     * @param format ("yyyy-MM-dd :hh:mm:ss")
     * @return
     */
    public static String getNowTime(String format) {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        System.out.println(dateFormat.format(date));
        return dateFormat.format(date);
    }

    /**
     * 获取两个日期相差的月数
     *
     * @param d1 较大的日期
     * @param d2 较小的日期
     * @return 如果d1>d2返回 月数差 否则返回0
     */
    public static int getMonthDiff(String d1, String d2, String format) {
        DateFormat df = new SimpleDateFormat(format);
        Date dt1 = null;
        Date dt2 = null;
        try {
            dt1 = df.parse(d1);
            dt2 = df.parse(d2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(dt1);
        c2.setTime(dt2);
//        if(c1.getTimeInMillis() < c2.getTimeInMillis()) return 0;
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        // 获取年的差值 假设 d1 = 2015-8-16 d2 = 2011-9-30
        int yearInterval = year1 - year2;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if (month1 < month2 || month1 == month2 && day1 < day2) yearInterval--;
        // 获取月数差值
        int monthInterval = (month1 + 12) - month2;
        if (day1 < day2) monthInterval--;
        monthInterval %= 12;
        return yearInterval * 12 + monthInterval;
    }

    /**
     * 获取两个日期的时间差
     **/
    public static int getMonthSpace(String d1, String d2, String format) {
        DateFormat df = new SimpleDateFormat(format);
        Date date1 = null;
        Date date2 = null;
        try {
            date1 = df.parse(d1);
            date2 = df.parse(d2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(date1);
        c2.setTime(date2);
        int month = c2.get(Calendar.MONTH) - c1.get(Calendar.MONTH);
        int date = c2.get(Calendar.DATE) - c1.get(Calendar.DATE);
        int year = c2.get(Calendar.YEAR) - c1.get(Calendar.YEAR);
        date = date <= 0 ? 1 : 0;
        int a = Math.abs(year * 12 + month)+date;
        return a;
    }


    /**
     * 比较两个日期相差的天数
     *
     * @param a
     * @param b
     * @return
     */
    public static int differentDays(String a, String b) {
        DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");

        Date date1 = new Date();
        Date date2 = new Date();

        try {
            date1 = format1.parse(a);
            date2 = format1.parse(b);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2)   //同一年
        {
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)    //闰年
                {
                    timeDistance += 366;
                } else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2 - day1);
        } else    //不同年
        {
            System.out.println("判断day2 - day1 : " + (day2 - day1));
            return day2 - day1;
        }
    }


    public static void main(String[] args) {

        //System.out.println(DateUtils.differentDays("2020-10-09", "2020-10-31"));
        System.out.println(DateUtils.getMonthDiff("2019-11-09", "2020-11-31", "yyyy-MM"));

    }
}
